﻿using Meow.Editor.AssetImport;
using Meow.Editor.Spatial;
using Microsoft.Xna.Framework;
using Myra.Graphics2D.UI;
using Myra.Graphics2D.UI.File;
using System;
using System.IO;


namespace Meow.Editor.UI;

public class FBXImporterSettings
{
    public int VertexToLoad;
    public bool ImportFaces;
    public FBXImporterSettings()
    {
        ImportFaces = true;

        VertexToLoad |= (int)VertexContent.Position;
        VertexToLoad |= (int)VertexContent.Normal;
        VertexToLoad |= (int)VertexContent.TangentBasis;
        VertexToLoad |= (int)VertexContent.BoneWeights;
        VertexToLoad |= (int)VertexContent.Texcoord1;
        VertexToLoad |= (int)VertexContent.Color1;
    }
}


internal class ModelImporter : Panel, IEditorWorker
{
    Editor _editor;
    FBXImporter _importer;
    int _meshImportContentMask;
    FBXImporterSettings importerSettings = new FBXImporterSettings();

    Myra.Graphics2D.Thickness marginLabel = new Myra.Graphics2D.Thickness(5, 10);
    Myra.Graphics2D.Thickness paddingLabel = new Myra.Graphics2D.Thickness(5, 5);
    Myra.Graphics2D.Thickness marginButton = new Myra.Graphics2D.Thickness(5, 5);
    Myra.Graphics2D.Thickness paddingButton = new Myra.Graphics2D.Thickness(10, 5);

    public ModelImporter(Editor editor)
    {
        _editor = editor;

        label_ModelName = new Label()
        {
            Text = " Path: ",
            Padding = paddingLabel,
            Margin = marginLabel,
        };
        label_ModelName.SetRowCol(0, 0);

        text_ModelPath = new TextBox()
        {
            Padding = marginLabel,
            Margin = paddingLabel,
            
        };
        text_ModelPath.TextChanged += (s, a) =>
        {
            if (Directory.Exists(text_ModelPath.Text) || File.Exists(text_ModelPath.Text))
                text_ModelPath.TextColor = Color.AliceBlue;
            else
                text_ModelPath.TextColor = Color.Red;
        };
        text_ModelPath.Text = "./";
        text_ModelPath.SetRowCol(0, 1);

        butn_OpenFile = Button.CreateTextButton("Open");
        butn_OpenFile.Tooltip = "Open a FileDialog to browse the model";
        butn_OpenFile.Click += (sender, args) => OpenFile();
        butn_OpenFile.Padding = paddingButton;
        butn_OpenFile.Margin = marginButton;
        butn_OpenFile.SetRowCol(1, 0);

        _gridRight = new Grid();
        _gridRight.ColumnSpacing = 8;
        _gridRight.RowSpacing = 8;
        _gridRight.DefaultRowProportion = new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        };
        _gridRight.RowsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        });
        _gridRight.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        });
        _gridRight.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        });
        _gridRight.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Fill,
        });
        _gridRight.Id = "_gridRight";
        _gridRight.Widgets.Add(label_ModelName);
        _gridRight.Widgets.Add(text_ModelPath);
        _gridRight.Widgets.Add(butn_OpenFile);

        var scrollViewer1 = new ScrollViewer();
        scrollViewer1.ShowHorizontalScrollBar = false;
        scrollViewer1.Content = _gridRight;

        _info = new Label();
        var gridInfo = new Grid();
        gridInfo.ColumnSpacing = 1;
        gridInfo.RowSpacing = 1;
        gridInfo.DefaultRowProportion = new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        };
        gridInfo.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        });
        gridInfo.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Auto,
        });
        gridInfo.ColumnsProportions.Add(new Proportion
        {
            Type = Myra.Graphics2D.UI.ProportionType.Fill,
        });
        gridInfo.Widgets.Add(_info);

        var scrollViewer2 = new ScrollViewer();
        scrollViewer2.ShowHorizontalScrollBar = false;
        scrollViewer2.Content = gridInfo;

        var verticalSplitPane1 = new VerticalSplitPane();
        verticalSplitPane1.Widgets.Add(scrollViewer2);
        //verticalSplitPane1.Widgets.Add(grid2);

        var horizontalSplitPane1 = new HorizontalSplitPane();
        StackPanel.SetProportionType(horizontalSplitPane1, Myra.Graphics2D.UI.ProportionType.Fill);
        horizontalSplitPane1.Widgets.Add(scrollViewer1);
        horizontalSplitPane1.Widgets.Add(verticalSplitPane1);


        _mainMenu = new MenuCommon(editor);

        var verticalStackPanel1 = new VerticalStackPanel();
        verticalStackPanel1.Spacing = 8;
        verticalStackPanel1.Widgets.Add(_mainMenu);
        verticalStackPanel1.Widgets.Add(horizontalSplitPane1);

        this.Widgets.Add(verticalStackPanel1);

        var labelNode = new Label()
        {
            Text = " Nodes:",
            Padding = paddingLabel,
            Margin = marginLabel,
        };
        labelNode.SetRowCol(2, 0);
        _gridRight.Widgets.Add(labelNode);

        _tree = new TreeView();
        _tree.SetRowCol(2, 1);
        Grid.SetColumnSpan(_tree, 2);
        _gridRight.Widgets.Add(_tree);
    }

    MenuCommon _mainMenu;

    Label label_ModelName;
    TextBox text_ModelPath;
    Button butn_OpenFile;

    Grid _gridRight;

    Label _info;

    TreeView _tree;

    public void OpenFile()
    {
        var fileDialog = new FileDialog(FileDialogMode.OpenFile);
        fileDialog.ShowModal(Desktop);

        fileDialog.FilePath = System.IO.Path.GetFullPath(text_ModelPath.Text);

        fileDialog.Closed += (s, a) =>
        {
            if (!fileDialog.Result)
            {
                return;
            }

            text_ModelPath.Text = fileDialog.FilePath;


            _importer = new FBXImporter();
            Node3D root = new Node3D();

            if (_importer.LoadFBX(fileDialog.FilePath, ref root, importerSettings) != ImportState.Succeed)
                throw new System.Exception("Import Fail");

            var node1 = _tree.AddSubNode(new ModelNodeLabel
            {
                Text = root.Name
            });

            foreach (var node in root.GetChildrens())
            {
                AddToTree(node, node1);
            }

            var strInfo = "";
            foreach (var mesh in _importer.RawMeshes)
            {
                strInfo += "Meshes: " + mesh.Root.Name + "\n";

                strInfo += "\t Positions: \t" + mesh.Positions.Length + "\n";
                strInfo += "\t Normals: \t" + mesh.Normals.Length + "\n";
                strInfo += "\t Tangents: \t" + mesh.Tangents.Length + "\n";
                strInfo += "\t BiTangents: \t" + mesh.BiTangents.Length + "\n";
                strInfo += "\t -------" + "\n";
                strInfo += "\t SkinnedBones: \t" + mesh.SkinnedBones.Count + "\n";
                strInfo += "\t BoneWeights: \t" + mesh.BoneWeights.Length + "\n";
                strInfo += "\t -------" + "\n";
                strInfo += "\t Faces: \t" + mesh.Faces.Length + "\n";
            }

            _info.Text = "Meshes: " + _importer.RawMeshes.Count + "\n" +
            "Skeletons: " + _importer.RawSkeletons.Count + "\n" + strInfo;

            Console.WriteLine("Meshes: " + _importer.RawMeshes.Count);
            Console.WriteLine("Skeletons: " + _importer.RawSkeletons.Count);

            foreach (var mesh in _importer.RawMeshes)
            {
                Console.WriteLine("Meshes: " + mesh.Root.Name);

                Console.WriteLine("\t Positions: \t" + mesh.Positions.Length);
                Console.WriteLine("\t Normals: \t" + mesh.Normals.Length);
                Console.WriteLine("\t Tangents: \t" + mesh.Tangents.Length);
                Console.WriteLine("\t BiTangents: \t" + mesh.BiTangents.Length);
                Console.WriteLine("\t -------");
                Console.WriteLine("\t SkinnedBones: \t" + mesh.SkinnedBones.Count);
                Console.WriteLine("\t BoneWeights: \t" + mesh.BoneWeights.Length);
                Console.WriteLine("\t -------");
                Console.WriteLine("\t Faces: \t" + mesh.Faces.Length);
            }

        };

    }

    void AddToTree(Node3D node, TreeViewNode parent)
    {
        var label = new ModelNodeLabel()
        {
            Text = node.Name,
        };

        foreach (var skl in _importer.RawSkeletons)
        {
            label.Type = skl.BoneNodes.Contains(node) ? ModelNodeType.Bone : label.Type;
        }
        foreach (var mesh in _importer.RawMeshes)
        {
            label.Type = mesh.Root == node ? ModelNodeType.Mesh : label.Type;
        }
        

        var treeNode = parent.AddSubNode(label);

        foreach (var child in node.GetChildrens())
        {
            AddToTree(child, treeNode);
        }
    }

    void IEditorWorker.Update(GameTime gameTime)
    {
        //foreach(var treeNode in _tree.GetChildren())
        //{
        //}
    }

    void IEditorWorker.Draw(GameTime gameTime, GraphicsDeviceManager gdm)
    {
        throw new System.NotImplementedException();
    }
}

public enum ModelNodeType
{
    Node,
    Mesh,
    Bone,
}

public class ModelNodeLabel : Label
{
    public ModelNodeType Type;
}